package com.axon.mvc.patterns.mediator
{
	import com.axon.base.helpers.AxFailure;
	import com.axon.base.helpers.AxReflectionUtils;
	import com.axon.base.managers.AxErrorManager;
	import com.axon.base.managers.AxPopUpManager;
	import com.axon.components.interfaces.IAxSmartContainter;
	import com.axon.mvc.events.AxViewEvent;
	import com.axon.mvc.helpers.AxMvcUtils;
	import com.axon.mvc.helpers.AxVerbs;
	import com.axon.mvc.patterns.facade.AxFacade;
	
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	
	import mx.controls.Alert;
	import mx.core.IFlexDisplayObject;
	import mx.events.CloseEvent;
	
	import org.puremvc.as3.interfaces.IMediator;
	import org.puremvc.as3.interfaces.INotification;

	public class AxMediatorPopUp extends AxMediator implements IMediator
	{
		//////////////////////////////////////////////////////////////////////////////////////////////////////
		
		private		var fParent					: DisplayObject = null;
		private		var fModal					: Boolean		= true;
		private		var fChildList				: String		= "";
		private		var fResponseNeededToShow	: Object		= null;
		private		var fTitleAndTextErrorMsg	: Object		= null;
		private		var fDataChanged			: Boolean		= true;

		protected	var fVo						: Object		= null;

		private		var fResult					: uint			= 0;

		//////////////////////////////////////////////////////////////////////////////////////////////////////
		
		public var warnIfExitWithoutSave: Boolean = false;
		public var dataChanged			: Boolean = false;
		
		//////////////////////////////////////////////////////////////////////////////////////////////////////
		
		public function AxMediatorPopUp(	parent					: DisplayObject, 
											vo						: Object		= null,
											responseNeededToShow	: Object		= null,
											titleAndTextErrorMsg	: Object		= null,  
											mediatorName			: String		= null,
											modal					: Boolean		= true, 
											childList				: String		= null ) 
		{
			if ( (!mediatorName) || (mediatorName == "") )
				mediatorName = AxReflectionUtils.getClassNameByInstance(this);
				
			super(null, mediatorName);
			
			fNotificationInterestList.push( AxVerbs.APP_RESIZE );
			
			fParent					= parent;
			fVo						= vo;
			fResponseNeededToShow	= responseNeededToShow;
			fTitleAndTextErrorMsg	= titleAndTextErrorMsg; 
			fModal					= modal;
			fChildList				= childList;

			if ( !fResponseNeededToShow ) {
				
				 showPopUp(); }

			else {

				if ( !fResponseNeededToShow.hasOwnProperty(AxMvcUtils.TERM_MODEL) || 
					 !fResponseNeededToShow.hasOwnProperty(AxMvcUtils.TERM_REQUEST_NAME) ) {					
					
					AxErrorManager.showFailure( new AxFailure(
						"Message for Software Engineers:\n\nHey guys, param 'responseNeededToShow' " +
						"for AxMediatorPopUp descendants constructors must be null or an Object like this: " +
						"{ model: aClass, requestName: aString }.") ); }
				
				else {
				
					fNotificationInterestList.push( 
						AxReflectionUtils.getClassNameByRef( fResponseNeededToShow[AxMvcUtils.TERM_MODEL] ) +
						AxMvcUtils.removeAxVerbPrefix(responseNeededToShow[AxMvcUtils.TERM_REQUEST_NAME]) +
						AxMvcUtils.SUFIX_SUCCESS );

					fNotificationInterestList.push( 
						AxReflectionUtils.getClassNameByRef( fResponseNeededToShow[AxMvcUtils.TERM_MODEL] ) +
						AxMvcUtils.removeAxVerbPrefix(responseNeededToShow[AxMvcUtils.TERM_REQUEST_NAME]) +
						AxMvcUtils.SUFIX_FAILURE ); 
				} 
			} 

			if ( fTitleAndTextErrorMsg ) {
			
				if ( !fTitleAndTextErrorMsg.hasOwnProperty(AxMvcUtils.TERM_TITLE) )
					fTitleAndTextErrorMsg[AxMvcUtils.TERM_TITLE] = "Erro"  //TODO - Internacionalização
			
				if ( !fTitleAndTextErrorMsg.hasOwnProperty(AxMvcUtils.TERM_TITLE) ) 					
					
					AxErrorManager.showFailure( new AxFailure(
						"Message for Software Engineers:\n\nHey guys, param 'titleAndTextErrorMsg' " +
						"for AxMediatorPopUp descendants constructors must be null or an Object like this: " +
						"{ title: aString, text: aString }.") );
				
			}
		}
		
		//////////////////////////////////////////////////////////////////////////////////////////////////////
		
		override protected function onViewEventFired(event: AxViewEvent): void
		{
			if (event.target == viewComponent)
			{
				switch (event.name)
				{
					case 	AxVerbs.DATA_CHANGE	: onDataChangePrivate(event);		break;
					case 	AxVerbs.OK			: onOkPrivate(event);				break;
					case 	AxVerbs.CANCEL		: onCancelOrClosePrivate(event);	break;
					case 	AxVerbs.CLOSE		: onCancelOrClosePrivate(event);	break;
					default						: super.onViewEventFired(event);
				}
			}
		}
		
		//////////////////////////////////////////////////////////////////////////////////////////////////////
		
		private function onDataChangePrivate(event: AxViewEvent): void
		{
			fDataChanged = true;
			
			if ( this.hasOwnProperty(AxMvcUtils.PREFIX_EVENT + AxMvcUtils.removeAxVerbPrefix(event.name)) )
				super.onViewEventFired(event);
		}

		//////////////////////////////////////////////////////////////////////////////////////////////////////
		
		private function onOkPrivate(event: AxViewEvent): void
		{
			fResult = Alert.OK;
			
			if ( this.hasOwnProperty(AxMvcUtils.PREFIX_EVENT + AxMvcUtils.removeAxVerbPrefix(event.name)) )
				super.onViewEventFired(event);
			else
				AxPopUpManager.closePopUpWindow(viewComponent as IFlexDisplayObject);
		}
		
		//////////////////////////////////////////////////////////////////////////////////////////////////////
		
		private function onCancelOrClosePrivate(event: AxViewEvent): void
		{
			fResult = (event.type == AxVerbs.CANCEL) ? Alert.CANCEL : Alert.OK;

			if (canCloseOrCancelPrivate()) 
			{
				if ( this.hasOwnProperty(AxMvcUtils.PREFIX_EVENT + AxMvcUtils.removeAxVerbPrefix(event.name)) )
					super.onViewEventFired(event);
				else {
					closePopUp();
				}
			}
		}
		
		//////////////////////////////////////////////////////////////////////////////////////////////////////
		
		private function canCloseOrCancelPrivate(): Boolean
		{
//			if (warnIfExitWithoutSave && fDataChanged)
			return canClose();	
		}

		//////////////////////////////////////////////////////////////////////////////////////////////////////
		
		protected function canClose(): Boolean { return true; }

		//////////////////////////////////////////////////////////////////////////////////////////////////////
		
		private function showPopUp( sender: Object = null, body: Object = null, extraInfo: Object = null ): void
		{
			var viewComponentClass: Class =  AxMvcUtils.getViewClassRefByMediatorInstance(this);
			var window: IFlexDisplayObject = AxPopUpManager.createPopUp(fParent, viewComponentClass, fModal, fChildList);

			setViewComponent( window );

			if (body)
				fVo = body;
				
			if (window is IAxSmartContainter) {

				(window as IAxSmartContainter).vo = fVo;
				viewValueObjectOk();
			}				 
				 
			viewComponent.addEventListener ( AxVerbs.DATA_CHANGE,	onDataChangePrivate );
			viewComponent.addEventListener ( AxVerbs.OK, 			onOkPrivate );
			viewComponent.addEventListener ( AxVerbs.CANCEL, 		onCancelOrClosePrivate );
			viewComponent.addEventListener ( AxVerbs.CLOSE, 		onCancelOrClosePrivate );
		}
		
		//////////////////////////////////////////////////////////////////////////////////////////////////////
		
		protected function viewValueObjectOk(): void { }
		
		//////////////////////////////////////////////////////////////////////////////////////////////////////
		
		public function closePopUp(unregisterMediator: Boolean = true): void
		{
			AxPopUpManager.closePopUpWindow(viewComponent as IFlexDisplayObject);
			
			if (unregisterMediator)
				AppFacade(facade).unregMediator(this);
		}
		
		//////////////////////////////////////////////////////////////////////////////////////////////////////
		
		public override function handleNotification(notification: INotification): void
		{
			var name		: String =	notification.getName();
			
			var sender		: Object =	notification.getBody().hasOwnProperty(AxMvcUtils.TERM_SENDER) ?
										notification.getBody().sender :
										notification.getBody();
			
			var body		: Object =	notification.getBody().hasOwnProperty(AxMvcUtils.TERM_BODY) ?
										notification.getBody().body :
										notification.getBody();
			
			var extraInfo	: Object =	notification.getBody().hasOwnProperty(AxMvcUtils.TERM_EXTRA_INFO) ?
										notification.getBody().extraInfo :
										null;

			// Application resize

			if ( name == AxVerbs.APP_RESIZE ) {

				AxPopUpManager.centerPopUp(viewComponent as IFlexDisplayObject); }
					
			// Mediator don't need response to show popup window

			else if ( !fResponseNeededToShow ) {

				super.handleNotification( notification ); }

			// Mediator need response to show popup window, but the respond do not depend on a proxy

			else if ( !fResponseNeededToShow.hasOwnProperty(AxMvcUtils.TERM_MODEL) || 
				(fResponseNeededToShow[AxMvcUtils.TERM_MODEL] == null) ) {

				if ( AxMvcUtils.removeAxVerbPrefix(name) == fResponseNeededToShow[AxMvcUtils.TERM_REQUEST_NAME] )

					handleResponseNeededToShowSuccess(sender, body, extraInfo);

				else

					super.handleNotification( notification ); 
				}

			// Mediator need response to show popup window, and the respond depend on a proxy

			else {
				
				if ( AxMvcUtils.removeAxVerbPrefix(name) ==   
					AxReflectionUtils.getClassNameByRef(fResponseNeededToShow[AxMvcUtils.TERM_MODEL]) +
					AxMvcUtils.removeAxVerbPrefix(fResponseNeededToShow[AxMvcUtils.TERM_REQUEST_NAME]) +
					AxMvcUtils.SUFIX_SUCCESS ) {
						
					handleResponseNeededToShowSuccess(sender, body, extraInfo); }
	
				else if ( AxMvcUtils.removeAxVerbPrefix(name) == 
					AxReflectionUtils.getClassNameByRef(fResponseNeededToShow[AxMvcUtils.TERM_MODEL]) +
					AxMvcUtils.removeAxVerbPrefix(fResponseNeededToShow[AxMvcUtils.TERM_REQUEST_NAME]) +
					AxMvcUtils.SUFIX_FAILURE ) {
						
						handleResponseNeededToShowFailure(sender, body, extraInfo); }
	
				else {
					
					super.handleNotification( notification );
				}
			}
		}

		//////////////////////////////////////////////////////////////////////////////////////////////////////
		
		public function handleResponseNeededToShowSuccess( sender: Object, body: Object, extraInfo: Object ): void
		{
			showPopUp(sender, body, extraInfo);
		}
		
		//////////////////////////////////////////////////////////////////////////////////////////////////////
		
		public function handleResponseNeededToShowFailure( sender: Object, body: Object, extraInfo: Object ): void
		{
			if (!fTitleAndTextErrorMsg.hasOwnProperty(AxMvcUtils.TERM_TEXT))
				AxPopUpManager.messageDlg(
					"Impossível abrir janela de popup", 
					"Erro", 
					Alert.OK, 
					fParent as Sprite); 
			else 
				AxPopUpManager.messageDlg(
					fTitleAndTextErrorMsg[AxMvcUtils.TERM_TEXT], 
					fTitleAndTextErrorMsg.hasOwnProperty(AxMvcUtils.TERM_TITLE) ? fTitleAndTextErrorMsg[AxMvcUtils.TERM_TITLE] : "Erro", 
					Alert.OK, 
					fParent as Sprite);
					
			AxFacade(facade).unregMediator(this);
		}
		
		//////////////////////////////////////////////////////////////////////////////////////////////////////
		
		public function brcastApplicationResize(sender: Object, body: Object, extraInfo: Object): void
		{
			AxPopUpManager.centerPopUp(viewComponent as IFlexDisplayObject);
		}
		
	}
}